/*
    Planner.cpp

    Date:
        05-09-10

    Descripton:
        A new calendar-interface concept using a
        12-hour clock planner for appointments,
        tasks, and deadlines

    Authors:
        Nathaniel Brown
        Subodh Prabhu
        Jesus Suarez
*/


/****************************************************************************/
/*                              I N C L U D E S                             */
/****************************************************************************/

#include "GlutHeaders.h"
#include "Clock.h"
#include "Calendar.h"
#include "Events.h"
#include "Text.h"
#include "Theme.h"
#include "setup/Setup.h"
#include "Selection.h"

/****************************************************************************/
/*                           G L O B A L   D A T A                          */
/****************************************************************************/

/* -------------------------------- Objects ------------------------------- */

Clock clk;
Calendar cal;
Text * description = NULL;
Text * menuBox = NULL;
Text * about1 = NULL;
Text * about2 = NULL;
Text * about3 = NULL;
Text * about4 = NULL;
Text * about5 = NULL;
Text * okay = NULL;
Events events;
Item * selectedItem;
Theme thm;
Setup * setupObj = NULL;

/* -------------------------- Window Information -------------------------- */

bool fullscreen = false;
int mainWin, descWin;         // window handles
int currentWindowHeight = SCREEN_H;
int currentWindowWidth = SCREEN_W;
int mainMenu;
bool runSetup = false;
bool setTheme(int option);
bool drawAbout = false;

/****************************************************************************/
/*                       O P E N G L   C A L B A C K S                      */
/****************************************************************************/

/* ---------------------- Main Window Initialization ---------------------- */

void init() {
  glPushMatrix();
  gluOrtho2D (0, currentWindowWidth - 1, currentWindowHeight - 1, 0);
  glViewport(0, currentWindowWidth - 1, currentWindowHeight - 1, 0);
  setTheme(OPT_THM_ZEBRA);
  glClearColor(thm.clearColor.r, thm.clearColor.g, thm.clearColor.b, thm.clearColor.t);
  glShadeModel (GL_FLAT);
  glEnable (GL_BLEND);
  glEnable (GL_LINE_SMOOTH);
  glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
  glHint (GL_POLYGON_SMOOTH_HINT, GL_NICEST);
  glHint (GL_POINT_SMOOTH_HINT, GL_NICEST);
  glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  bool calendar_created = false;
  string filename = "";
  
  about1 = new Text("                                             About", 50, 50);
  about2 = new Text("         Planner is a radial calendar interface that uses the standard ical file format.", 50, 80);
  about3 = new Text("                                    Planner is new and unique.", 50, 94);
  about4 = new Text(" ", 50, 108);
  about5 = new Text("     Planner is Nate Brown, Subodh Prabhu, Jo Anne Rodriguez, Mike Simon, and Jesus Suarez.", 50, 122);
  okay   = new Text("OK", 410, 200);
  
  //runSetup = true;
  //setupObj = new Setup();
  
  // temp
  filename = "test_files/testcal.ics";
  calendar_created = Calendar::createFromFile(&cal, filename.c_str());
  
  while(!calendar_created) {
    cout << "Enter an iCalendar filename: ";
    cin >> filename;
    calendar_created = Calendar::createFromFile(&cal, filename.c_str());
  }
}


/* ---------------------- Main Window Display Calback --------------------- */

void display(void) {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  clk.drawFace();
  events.populate();
  events.draw();
  clk.drawHand();
  
  // text stuff
  menuBox->drawMenuText();
  if(description) {
    description->draw();
  }
  if(drawAbout) {
    // clear the screen
    glClearColor(thm.clearColor.r, thm.clearColor.g, thm.clearColor.b, thm.clearColor.t);
    glClear(GL_COLOR_BUFFER_BIT);
    
    about1->drawPlainText();
    about2->drawPlainText();
    about3->drawPlainText();
    about4->drawPlainText();
    about5->drawPlainText();
    okay->drawMenuText();
  }

  if(runSetup && setupObj){
    setupObj->drawSetup();
  }

  glutSwapBuffers();
  glutPostRedisplay();
}

bool writeSomething(string write, int x, int y) {
    if(x<0 || y<0 || x>currentWindowWidth || y>currentWindowHeight) {
        if(description) {
            description->Text::~Text();
            description = NULL;
        } 
        return false;
    }
    if(description) {
        description->Text::~Text();
    }
    description = new Text(write, x, y);
    return true;
}

/* ---------------------------- Toggle Fullscreen ---------------------------- */

void togFullScreen() {
      if(!fullscreen) {
        glutFullScreen();
        fullscreen = true;
        currentWindowHeight = glutGet(GLUT_SCREEN_HEIGHT);
        currentWindowWidth = glutGet(GLUT_SCREEN_WIDTH);
        glPopMatrix();
        glPushMatrix();
        gluOrtho2D (0, currentWindowWidth - 1, currentWindowHeight - 1, 0);
      }
      else {
        glutReshapeWindow(SCREEN_W, SCREEN_H);        /* Restore us */
        glutPositionWindow(0,0);
        fullscreen = false;
        currentWindowWidth = SCREEN_W;
        currentWindowHeight = SCREEN_H;
        glPopMatrix();
        glPushMatrix();
        gluOrtho2D (0, currentWindowWidth - 1, currentWindowHeight - 1, 0);
      }
}

/* ------------------------------- About ----------------------------------- */

void aboutPlanner() {
    drawAbout = !drawAbout;
    glutSwapBuffers();
    glutPostRedisplay();
}

/* ------------------------------- Exit ----------------------------------- */

void exitPlanner() {
      exit(0);
}

/* ---------------------------- Mouse Callback ---------------------------- */

void mouse(int button, int state, int x, int y) {
    if(runSetup && setupObj && state == GLUT_UP){
        setupObj->mouseClickOnButton(x, y);
        return;
    }
    if(state == GLUT_DOWN && button == GLUT_RIGHT_BUTTON) {
        writeSomething("Lorem ipsum \ndolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", x, y);
        glutSwapBuffers();
        glutPostRedisplay();
    }
    else if(state == GLUT_UP && button == GLUT_LEFT_BUTTON && drawAbout) {
        drawAbout = !drawAbout;
    }
    else if(state == GLUT_UP && button == GLUT_MIDDLE_BUTTON){
        writeSomething("",-1,-1); // clear box
    }
}

/* ------------------------- Mouse Motion Callback ------------------------ */

void motion(int x, int y) {
  if(menuBox->positionIsInMenu(x, y)){
      glutSetMenu(mainMenu);
      glutAttachMenu(GLUT_LEFT_BUTTON);
  }
  else{
      glutSetMenu(mainMenu);
      glutDetachMenu(GLUT_LEFT_BUTTON);
      if(Selection::getSelectedItem(x, y)) {
        string message = selectedItem->getTitle();
        //message.append("Title, time, etc");
        writeSomething(message, x, y);
      }
  }
}

/* ----------------------------- Menu Handler ----------------------------- */

void menuHandler(int option) {
  switch(option) {
  case OPT_THM_ZEBRA:
    setTheme(option);
    glClearColor(thm.clearColor.r, thm.clearColor.g, thm.clearColor.b, thm.clearColor.t);
    break;
  case OPT_THM_GOGIRL:
    setTheme(option);
    glClearColor(thm.clearColor.r, thm.clearColor.g, thm.clearColor.b, thm.clearColor.t);
    break;
  case OPT_THM_DRACULA:
    setTheme(option);
    glClearColor(thm.clearColor.r, thm.clearColor.g, thm.clearColor.b, thm.clearColor.t);
    break;
  case OPT_THM_TAMU:
    setTheme(option);
    glClearColor(thm.clearColor.r, thm.clearColor.g, thm.clearColor.b, thm.clearColor.t);
    break;
  case OPT_MAIN_FULLSCR:
    togFullScreen();
    break;
  case OPT_MAIN_ABOUT:
    aboutPlanner();
    break;
  case OPT_MAIN_EXIT:
    exitPlanner();
    break;
  case OPT_RUN_SETUP:
    runSetup = true;
    setupObj = new Setup();
    break;
  default:
    cout << "ERROR: Invalid Menu option." << endl;
    break;
  }
}

/* -------------------------------- Init Menu ------------------------------ */

void initMenu() {
  int themeMenu = glutCreateMenu(menuHandler);
  glutAddMenuEntry("Clean",OPT_THM_ZEBRA);
  glutAddMenuEntry("Hello Kitty",OPT_THM_GOGIRL);
  glutAddMenuEntry("Passion",OPT_THM_DRACULA);
  glutAddMenuEntry("Fightin' Texas Aggie",OPT_THM_TAMU);
  int viewMenu = glutCreateMenu(menuHandler);
  glutAddMenuEntry("Toggle Full Screen",OPT_MAIN_FULLSCR);
  mainMenu = glutCreateMenu(menuHandler);
  glutAddSubMenu("Theme",themeMenu);
  glutAddSubMenu("View",viewMenu);
  glutAddMenuEntry("Setup",OPT_RUN_SETUP);
  glutAddMenuEntry("About",OPT_MAIN_ABOUT);
  glutAddMenuEntry("Exit",OPT_MAIN_EXIT);
  menuBox = new Text("Menu", 0, 0);
}

/* --------------------------- Keyboard Callback -------------------------- */

void keyboard(unsigned char key, int x, int y){
  switch(key) {
    case 'f':
      togFullScreen();
      break;
    case '?':
      aboutPlanner();
      break;
    #ifndef __APPLE__
    case 'q':
      exitPlanner();
      break;
    case 'x':
      exitPlanner();
      break;
    #endif
    default:
      break;
  }  
  glutPostRedisplay();
}


/****************************************************************************/
/*                                 M A I N                                  */
/****************************************************************************/

int main(int argc, char * argv[]) {  
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB);
  glutInitWindowSize(SCREEN_W, SCREEN_H);
  glutInitWindowPosition(0, 0);
  mainWin = glutCreateWindow ("Planner");
  init();
  glutKeyboardFunc(keyboard);
  glutDisplayFunc(display);
  glutMouseFunc(mouse);
  glutPassiveMotionFunc(motion);
  initMenu();

  glutMainLoop();
  return 0;
}
